package com.czf.testmodule.annotation;


import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * @author zfChen
 * @create 2022/6/30 16:29
 */
@Aspect
@Component
public class Proxy {

//    @Pointcut(value = "execution(* com.czf.testmodule.annotation.*.*(..))")
    @Pointcut("@annotation(CherryAnnotation)")
    public void pointCut(){
    }

    /*
    getArgs(): 获取方法的参数.
    getThis(): 获取代理对象.
    getTarget(): 获取目标对象.
    getSignature(): 获取方法签名.
    toString(): 获取方法描述.
     */

    @Before("pointCut()")
    public void annotation(JoinPoint joinPoint) throws InstantiationException, IllegalAccessException, NoSuchMethodException {
        System.out.println("---Before begin---");
        System.out.println("getArgs: " + Arrays.asList(joinPoint.getArgs()).stream().map(Object::toString).collect(Collectors.joining(",")));
        System.out.println("getThis: " + joinPoint.getThis());
        System.out.println("getTarget: " + joinPoint.getTarget());
        System.out.println("getSignature: " + joinPoint.getSignature());
        System.out.println("toString: " + joinPoint.toString());

        String[] parameterNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        Object[] args = joinPoint.getArgs();
        for (String str:
             parameterNames) {
            System.out.println(str);
        }

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        CherryAnnotation annotation = signature.getMethod().getAnnotation(CherryAnnotation.class);
        System.out.println(annotation.value());

        System.out.println("---Before  end---");
    }

    @After("pointCut()") // 返回通知
    public void after() {
        System.out.println("---After  begin---");
        System.out.println("---After  end---");

    }

    @AfterReturning(value = "pointCut()",returning = "obj") // 正常返回通知
    public void returning(JoinPoint joinPoint,Object obj) {
        System.out.println(obj);
        System.out.println("AfterReturning");
    }

    @AfterThrowing(value = "pointCut()", throwing = "throwing") // 异常返回通知
    public void logThrowing(JoinPoint joinPoint, Throwable throwing) {
        System.out.println("异常返回通知：" + joinPoint.getSignature().getDeclaringTypeName() + " 异常：");
        throwing.printStackTrace();
    }

    @Around("pointCut()") // 环绕通知
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("---Around begin---");
        Object proceed = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
        System.out.println("---Around end---");
        return proceed;
    }

}
